package MONITORING::MW::TOMCAT::THREADS;

#################################################################
# $LastChangedDate: 2013-11-25 15:03:06 +0000 (Mon, 25 Nov 2013) $
# $LastChangedRevision: 22 $
# $LastChangedBy: aswod_83@gmx.net $
#################################################################
use strict;
use base qw(moniCA::HTTP::REQUEST);
use XML::Simple;
use Data::Dumper;

#-------------------------------------------------------------------------------
sub Run {

#-------------------------------------------------------------------------------
# Description:
# Input Parms:
# Output Parms:
#-------------------------------------------------------------------------------
    my $self      = shift;
    my $cnf       = $self->GetCNF();
    my $logger    = $self->GetLogger();
    my $statefile = $self->TmpDir() . '/' . $self->Plug() . '.xml';
    my $oldstat;
    my %newstat;

    if ( -s $statefile ) {
        $oldstat = XMLin( $statefile, ForceArray => 1 );
    }

    $self->ConnectHTTP(@_);

    if ( $self->{HTTPRequest}->is_success ) {

        foreach (
            @{
                XMLin(
                    $self->{HTTPRequest}->content,
                    ForceArray => ['connector'],
                    KeyAttr    => []
                )->{connector}
            }
          )
        {
            if ( $cnf->{connector}->{ $_->{name} }->{threadInfo} ) {

                $self->Report( $_->{name} )
                  if (
                    $cnf->{connector}->{ $_->{name} }->{'Report'} =~ /true/i );

                foreach my $thread_key ( keys %{ $_->{threadInfo} } ) {

                    if ( $cnf->{connector}->{ $_->{name} }->{threadInfo}
                        ->{$thread_key} )
                    {
                        if ( $_->{threadInfo}->{$thread_key} >
                            $cnf->{connector}->{ $_->{name} }->{threadInfo}
                            ->{$thread_key}->{failCount} )
                        {
                            $newstat{connector}{ $_->{name} }{threadInfo}
                              {$thread_key}{failCount} =
                              ( $oldstat->{connector}->{ $_->{name} }
                                  ->{threadInfo}->{$thread_key}->{failCount} +
                                  1 )
                              || 1;
                            $newstat{connector}{ $_->{name} }{threadInfo}
                              {$thread_key}{warnCount} = 0;
                            if ( $newstat{connector}{ $_->{name} }{threadInfo}
                                {$thread_key}{failCount} == $cnf->{maxCount} )
                            {
                                $logger->error( "[Connector: "
                                      . $_->{name} . "] "
                                      . $thread_key . ": "
                                      . $_->{threadInfo}->{$thread_key}
                                      . " ($newstat{connector}{$_->{name}}{threadInfo}{$thread_key}{failCount})"
                                );
                            }
                            else {
                                $logger->warn( "[Connector: "
                                      . $_->{name} . "] "
                                      . $thread_key . ": "
                                      . $_->{threadInfo}->{$thread_key}
                                      . " ($newstat{connector}{$_->{name}}{threadInfo}{$thread_key}{failCount})"
                                );
                            }
                        }
                        elsif ( $_->{threadInfo}->{$thread_key} >
                            $cnf->{connector}->{ $_->{name} }->{threadInfo}
                            ->{$thread_key}->{warnCount} )
                        {
                            $newstat{connector}{ $_->{name} }{threadInfo}
                              {$thread_key}{warnCount} =
                              ( $oldstat->{connector}->{ $_->{name} }
                                  ->{threadInfo}->{$thread_key}->{warnCount} +
                                  1 )
                              || 1;
                            $newstat{connector}{ $_->{name} }{threadInfo}
                              {$thread_key}{failCount} = 0;
                            if ( $newstat{connector}{ $_->{name} }{threadInfo}
                                {$thread_key}{warnCount} == $cnf->{maxCount} )
                            {
                                $logger->warn( "[Connector: "
                                      . $_->{name} . "] "
                                      . $thread_key . ": "
                                      . $_->{threadInfo}->{$thread_key}
                                      . " ($newstat{connector}{$_->{name}}{threadInfo}{$thread_key}{warnCount})"
                                );
                            }
                            else {
                                $logger->info( "[Connector: "
                                      . $_->{name} . "] "
                                      . $thread_key . ": "
                                      . $_->{threadInfo}->{$thread_key}
                                      . " ($newstat{connector}{$_->{name}}{threadInfo}{$thread_key}{warnCount})"
                                );
                            }
                        }
                        else {
                            $newstat{connector}{ $_->{name} }{threadInfo}
                              {$thread_key}{warnCount} = 0;
                            $newstat{connector}{ $_->{name} }{threadInfo}
                              {$thread_key}{failCount} = 0;
                            $logger->info( "[Connector: "
                                  . $_->{name} . "] "
                                  . $thread_key . ": "
                                  . $_->{threadInfo}->{$thread_key} );
                        }

                    }
                    else {
                        $logger->debug( "missing config parameter [Connector: "
                              . $_->{name} . "] "
                              . $thread_key );
                        next;
                    }
                }
            }
            else {
                $logger->debug( "missing config parameter [Connector: "
                      . $_->{name}
                      . "]" );
                next;
            }
        }
        $newstat{connection} = 0;
    }
    else {
        $newstat{connection} = ( $oldstat->{connection} + 1 ) || 1;
        $newstat{connector} = $oldstat->{connector};
        if ( $newstat{connection} == $cnf->{maxCount} ) {
            $logger->error( "No Request for Instance (",
                $self->{HTTPRequest}->status_line, ")" );
        }
        else {
            $logger->warn( "No Request for Instance  (",
                $$self->{HTTPRequest}->status_line, ")" );
        }
    }

    XMLout( \%newstat, outputfile => $statefile, NoSort => 0 );
}

#-------------------------------------------------------------------------------
sub Report {

#-------------------------------------------------------------------------------
# Description:  Creating/Updating RRD File
# Input Parms:
# Output Parms: None
#-------------------------------------------------------------------------------
    my $self      = shift;
    my $connector = shift;
    my $logger    = $self->GetLogger();
    my $cnf       = $self->GetCNF();
    my $rrdfile   = $self->VarDir() . '/' . $self->Plug() . '.rrd';

    eval {
        require RRDs;

        if (  !-f $self->VarDir() . '/'
            . $self->Plug() . '_'
            . $connector
            . '.rrd' )
        {
            RRDs::create(
                $self->VarDir() . '/'
                  . $self->Plug() . '_'
                  . $connector . '.rrd',
                "--step=300",
                "DS:maxThreads:GAUGE:600:0:10000",
                "DS:currentThreadCount:GAUGE:600:0:10000",
                "DS:currentThreadsBusy:GAUGE:600:0:10000",
                "RRA:AVERAGE:0.5:1:800",
                "RRA:AVERAGE:0.5:6:800",
                "RRA:AVERAGE:0.5:24:800",
                "RRA:AVERAGE:0.5:288:800",
                "RRA:MAX:0.5:1:800",
                "RRA:MAX:0.5:6:800",
                "RRA:MAX:0.5:24:800",
                "RRA:MAX:0.5:288:800"
            );
            $logger->warn( "RRDs::create returns " . RRDs->error() )
              if ( RRDs->error );
        }

        if (  -f $self->VarDir() . '/'
            . $self->Plug() . '_'
            . $connector
            . '.rrd' )
        {
            RRDs::update(
                $self->VarDir() . '/'
                  . $self->Plug() . '_'
                  . $connector . '.rrd',
                '--template=maxThreads:currentThreadCount:currentThreadsBusy',
                'N' . ':'
                  . XMLin(
                    $self->{HTTPRequest}->content,
                    KeyAttr    => { connector => 'name' },
                    ForceArray => 1
                  )->{'connector'}->{$connector}->{'threadInfo'}->[0]
                  ->{'maxThreads'} . ':'
                  . XMLin(
                    $self->{HTTPRequest}->content,
                    KeyAttr    => { connector => 'name' },
                    ForceArray => 1
                  )->{'connector'}->{$connector}->{'threadInfo'}->[0]
                  ->{'currentThreadCount'} . ':'
                  . XMLin(
                    $self->{HTTPRequest}->content,
                    KeyAttr    => { connector => 'name' },
                    ForceArray => 1
                  )->{'connector'}->{$connector}->{'threadInfo'}->[0]
                  ->{'currentThreadsBusy'}
            );
            $logger->warn( "RRDs::update returns " . RRDs::error() )
              if ( RRDs::error() );
        }
        1;
    } or $logger->info( "Report incomplete: " . $@ );

}

1;

__END__
 
=pod
 
=head1 NAME
 
THREADS.pm - monitors service availability 
 
=head1 SYNOPSIS
 
=head1 DESCRIPTION
 
=head1 PREREQUISITES
 
The follwing CPAN modules needs to be installed:
 
C<Log::Log4perl>
C<XML::Simple>
C<IO::Socket::INET>
C<Time::HiRes>
=head1 CONFIGURATION FILE
 
  By default
 
=head2 EXAMPLES
 
=head3 example of configuation file
 
Modul 	    MONITORING::SYS::SOCKET_PORT
Logger		%LOGGER%
LogLevel	%PRIORITY%


<service %IDENTIFIER%>
						PeerAddr = %DESTINATION_IP%
 						PeerPort = %DESTINATION_PORT%
 						Proto = %PROTOCOL%
 						Timeout	= %TIMEOUT_SEC%
 						LocalAddr = %LOCAL_BIND_IP%
</service>

max_error_count =       3
 
=cut
